home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / gfx / misc / gnuplot-3.7src.lha / gnuplot-3.7src / gnuplot-3.7.lha / gnuplot-3.7 / binary.c < prev    next >
C/C++ Source or Header  |  1998-11-04  |  12KB  |  421 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: binary.c,v 1.10 1998/04/14 00:14:49 drd Exp $";
  3. #endif
  4.  
  5. /*
  6.  * The addition of gnubin and binary, along with a small patch
  7.  * to command.c, will permit gnuplot to plot binary files.
  8.  * gnubin  - contains the code that relies on gnuplot include files
  9.  *                     and other definitions
  10.  * binary      - contains those things that are independent of those 
  11.  *                     definitions and files
  12.  *
  13.  * With these routines, hidden line removal of your binary data is possible!
  14.  *
  15.  * Last update:  3/29/92 memory allocation bugs fixed. jvdwoude@hut.nl
  16.  *               3/09/92 spelling errors, general cleanup, use alloc with no
  17.  *                       nasty fatal errors
  18.  *               3/03/92 for Gnuplot 3.24.
  19.  * Created from code for written by RKC for gnuplot 2.0b.
  20.  *
  21.  * Copyright (c) 1991,1992 Robert K. Cunningham, MIT Lincoln Laboratory
  22.  *
  23.  */
  24.  
  25. #include "plot.h"        /* We have to get TRUE and FALSE */
  26. #include "stdfn.h"
  27. #include "binary.h"
  28.  
  29. /* 
  30.  * This routine scans the first block of the file to see if the file is a 
  31.  * binary file.  A file is considered binary if 10% of the characters in it 
  32.  * are not in the ascii character set. (values < 128), or if a NUL is found.
  33.  * I hope this doesn't break when used on the bizzare PC's.
  34.  */
  35. int is_binary_file(fp)
  36. register FILE *fp;
  37. {
  38.     register int i, len;
  39.     register int odd;        /* Contains a count of the odd characters */
  40.     long where;
  41.     register unsigned char *c;
  42.     unsigned char buffer[512];
  43.  
  44.     if ((where = ftell(fp)) == -1) {    /* Find out where we start */
  45.     fprintf(stderr, "Notice: Assuming unseekable data is not binary\n");
  46.     return (FALSE);
  47.     } else {
  48.     rewind(fp);
  49.  
  50.     len = fread(buffer, sizeof(char), 512, fp);
  51.     if (len <= 0)        /* Empty file is declared ascii */
  52.         return (FALSE);
  53.  
  54.     c = buffer;
  55.  
  56.     /* now scan buffer to look for odd characters */
  57.     odd = 0;
  58.     for (i = 0; i < len; i++, c++) {
  59.         if (!*c) {        /* NUL _never_ allowed in text */
  60.         odd += len;
  61.         break;
  62.         } else if ((*c & 128) ||    /* Meta-characters--we hope it's not formatting */
  63.                (*c == 127) ||    /* DEL */
  64.                (*c < 32 &&
  65.             *c != '\n' && *c != '\r' && *c != '\b' &&
  66.             *c != '\t' && *c != '\f' && *c != 27 /*ESC */ ))
  67.         odd++;
  68.     }
  69.  
  70.     fseek(fp, where, 0);    /* Go back to where we started */
  71.  
  72.     if (odd * 10 > len)    /* allow 10% of the characters to be odd */
  73.         return (TRUE);
  74.     else
  75.         return (FALSE);
  76.     }
  77. }
  78.  
  79.  
  80. /*========================= I/O Routines ================================
  81.   These may be useful for situations other than just gnuplot.  Note that I 
  82.   have included the reading _and_ the writing routines, so others can create 
  83.   the file as well as read the file.
  84. */
  85.  
  86. /*
  87.    This function reads a matrix from a stream
  88.  
  89.    This routine never returns anything other than vectors and arrays
  90.    that range from 0 to some number.  
  91.  
  92.  */
  93. #define START_ROWS 100        /* Each of these must be at least 1 */
  94. #define ADD_ROWS 50
  95. int fread_matrix(fin, ret_matrix, nr, nc, row_title, column_title)
  96. FILE *fin;
  97. float GPFAR *GPFAR * GPFAR * ret_matrix, GPFAR * GPFAR * row_title,
  98.  GPFAR * GPFAR * column_title;
  99. int *nr, *nc;
  100. {
  101.     float GPFAR *GPFAR * m, GPFAR * rt, GPFAR * ct;
  102.     register int num_rows = START_ROWS;
  103.     register int num_cols;
  104.     register int current_row = 0;
  105.     register float GPFAR *GPFAR * temp_array;
  106.     float fdummy;
  107.  
  108.     if (fread(&fdummy, sizeof(fdummy), 1, fin) != 1)
  109.     return FALSE;
  110.  
  111.     num_cols = (int) fdummy;
  112.  
  113.     /* 
  114.        Choose a reasonable number of rows,
  115.        allocate space for it and continue until this space
  116.        runs out, then extend the matrix as necessary.
  117.      */
  118.     ct = vector(0, num_cols - 1);
  119.     fread(ct, sizeof(*ct), num_cols, fin);
  120.  
  121.     rt = vector(0, num_rows - 1);
  122.     m = matrix(0, num_rows - 1, 0, num_cols - 1);
  123.  
  124.     while (fread(&rt[current_row], sizeof(rt[current_row]), 1, fin) == 1) {
  125.     /* We've got another row */
  126.     if (fread(m[current_row], sizeof(*(m[current_row])), num_cols, fin) != num_cols)
  127.         return (FALSE);    /* Not a True matrix */
  128.  
  129.     current_row++;
  130.     if (current_row >= num_rows) {    /* We've got to make a bigger rowsize */
  131.         temp_array = extend_matrix(m, 0, num_rows - 1, 0, num_cols - 1,
  132.                   num_rows + ADD_ROWS - 1, num_cols - 1);
  133.         rt = extend_vector(rt, 0, num_rows - 1, num_rows + ADD_ROWS - 1);
  134.  
  135.         num_rows += ADD_ROWS;
  136.         m = temp_array;
  137.     }
  138.     }
  139.     /*  finally we force the matrix to be the correct row size */
  140.     /*  bug fixed. procedure called with incorrect 6th argument.
  141.      *   jvdwoude@hut.nl */
  142.     temp_array = retract_matrix(m, 0, num_rows - 1, 0, num_cols - 1, current_row - 1, num_cols - 1);
  143.     /* Now save the things that change */
  144.     *ret_matrix = temp_array;
  145.     *row_title = retract_vector(rt, 0, num_rows - 1, current_row - 1);
  146.     *column_title = ct;
  147.     *nr = current_row;        /* Really the total number of rows */
  148.     *nc = num_cols;
  149.     return (TRUE);
  150. }
  151.  
  152. /* This writes a matrix to a stream 
  153.    Note that our ranges are inclusive ranges--and we can specify subsets.
  154.    This behaves similarly to the xrange and yrange operators in gnuplot
  155.    that we all are familiar with.
  156.  */
  157. int fwrite_matrix(fout, m, nrl, nrh, ncl, nch, row_title, column_title)
  158. register FILE *fout;
  159. register float GPFAR *GPFAR * m, GPFAR * row_title, GPFAR * column_title;
  160. register int nrl, nrh, ncl, nch;
  161. {
  162.     register int j;
  163.     float length;
  164.     register int col_length;
  165.     register int status;
  166.     float GPFAR *title = NULL;
  167.  
  168.     length = (float) (col_length = nch - ncl + 1);
  169.  
  170.     if ((status = fwrite((char *) &length, sizeof(float), 1, fout)) != 1) {
  171.     fprintf(stderr, "fwrite 1 returned %d\n", status);
  172.     return (FALSE);
  173.     }
  174.     if (!column_title) {
  175.     column_title = title = vector(ncl, nch);
  176.     for (j = ncl; j <= nch; j++)
  177.         title[j] = (float) j;
  178.     }
  179.     fwrite((char *) column_title, sizeof(float), col_length, fout);
  180.     if (title) {
  181.     free_vector(title, ncl, nch);
  182.     title = NULL;
  183.     }
  184.     if (!row_title) {
  185.     row_title = title = vector(nrl, nrh);
  186.     for (j = nrl; j <= nrh; j++)
  187.         title[j] = (float) j;
  188.     }
  189.     for (j = nrl; j <= nrh; j++) {
  190.     fwrite((char *) &row_title[j], sizeof(float), 1, fout);
  191.     fwrite((char *) (m[j] + ncl), sizeof(float), col_length, fout);
  192.     }
  193.     if (title)
  194.     free_vector(title, nrl, nrh);
  195.  
  196.     return (TRUE);
  197. }
  198.  
  199. /*===================== Support routines ==============================*/
  200.  
  201. /******************************** VECTOR *******************************
  202.  *       The following routines interact with vectors.
  203.  *
  204.  *   If there is an error we don't really return - int_error breaks us out.
  205.  *
  206.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  207.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  208.  *
  209.  */
  210. float GPFAR *vector(nl, nh)
  211. register int nl, nh;
  212. {
  213.     register float GPFAR *vec;
  214.  
  215.     if (!(vec = (float GPFAR *) gp_alloc((unsigned long) (nh - nl + 1) * sizeof(float), NULL))) {
  216.     int_error("not enough memory to create vector", NO_CARET);
  217.     return NULL;        /* Not reached */
  218.     }
  219.     return (vec - nl);
  220. }
  221.  
  222.  
  223. /* 
  224.  *  Free a vector allocated above
  225.  *
  226.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  227.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  228.  *
  229.  */
  230. void free_vector(vec, nl, nh)
  231. float GPFAR *vec;
  232. int nl, nh;
  233. {
  234.     free(vec + nl);
  235. }
  236.  
  237. /************ Routines to modify the length of a vector ****************/
  238. float GPFAR *
  239.  extend_vector(vec, old_nl, old_nh, new_nh)
  240. float GPFAR *vec;
  241. register int old_nl, old_nh, new_nh;
  242. {
  243.     register float GPFAR *new_v;
  244.     new_v = (float GPFAR *) gp_realloc((void *) (vec + old_nl),
  245.            (unsigned long) (new_nh - old_nl + 1) * sizeof(float),
  246.                        "extend vector");
  247.     return new_v - old_nl;
  248. }
  249.  
  250. float GPFAR *
  251.  retract_vector(v, old_nl, old_nh, new_nh)
  252. float GPFAR *v;
  253. register int old_nl, old_nh, new_nh;
  254. {
  255.     register float GPFAR *new_v;
  256.     new_v = (float GPFAR *) gp_realloc((void *) (v + old_nl),
  257.                        (unsigned long) (new_nh - old_nl + 1) * sizeof(float), "retract vector");
  258.     return new_v - old_nl;
  259. }
  260.  
  261.  
  262. /***************************** MATRIX ************************
  263.  *
  264.  *       The following routines work with matricies
  265.  *
  266.  *      I always get confused with this, so here I write it down:
  267.  *               for nrl<= nri <=nrh and
  268.  *               for ncl<= ncj <=nch
  269.  *  
  270.  *   This matrix is accessed as:
  271.  *   
  272.  *     matrix[nri][ncj];
  273.  *     where nri is the offset to the pointer to a vector where the
  274.  *     ncjth element lies.
  275.  * 
  276.  *   If there is an error we don't really return - int_error breaks us out.
  277.  *
  278.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  279.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  280.  *
  281.  */
  282. float
  283. GPFAR *GPFAR * matrix(nrl, nrh, ncl, nch)
  284. register int nrl, nrh, ncl, nch;
  285. {
  286.     register int i;
  287.     register float GPFAR *GPFAR * m;
  288.  
  289.     m = (float GPFAR * GPFAR *) gp_alloc((unsigned long) (nrh - nrl + 1) * sizeof(float GPFAR *), "matrix");
  290.     m -= nrl;
  291.  
  292.     for (i = nrl; i <= nrh; i++) {
  293.     if (!(m[i] = (float GPFAR *) gp_alloc((unsigned long) (nch - ncl + 1) * sizeof(float), NULL))) {
  294.         free_matrix(m, nrl, i - 1, ncl, nch);
  295.         int_error("not enough memory to create matrix", NO_CARET);
  296.         return NULL;
  297.     }
  298.     m[i] -= ncl;
  299.     }
  300.     return m;
  301. }
  302. /* 
  303.  * Free a matrix allocated above
  304.  *
  305.  *
  306.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  307.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  308.  *
  309.  */
  310. void free_matrix(m, nrl, nrh, ncl, nch)
  311. float GPFAR *GPFAR * m;
  312. unsigned nrl, nrh, ncl, nch;
  313. {
  314.     register unsigned int i;
  315.  
  316.     for (i = nrl; i <= nrh; i++)
  317.     free((char GPFAR *) (m[i] + ncl));
  318.     free((char GPFAR *) (m + nrl));
  319. }
  320.  
  321. /*
  322.    This routine takes a sub matrix and extends the number of rows and 
  323.    columns for a new matrix
  324.  */
  325. float GPFAR *GPFAR * extend_matrix(a, nrl, nrh, ncl, nch, srh, sch)
  326. register float GPFAR *GPFAR * a;
  327. register int nrl, nrh, ncl, nch;
  328. register int srh, sch;
  329. {
  330.     register int i;
  331.     register float GPFAR *GPFAR * m;
  332.  
  333.     m = (float GPFAR * GPFAR *) gp_realloc((void *) (a + nrl), (unsigned long) (srh - nrl + 1) * sizeof(float GPFAR *), "extend matrix");
  334.  
  335.     m -= nrl;
  336.  
  337.     if (sch != nch) {
  338.     for (i = nrl; i <= nrh; i++) {    /* Copy and extend rows */
  339.         if (!(m[i] = extend_vector(m[i], ncl, nch, sch))) {
  340.         free_matrix(m, nrl, nrh, ncl, sch);
  341.         int_error("not enough memory to extend matrix", NO_CARET);
  342.         return NULL;
  343.         }
  344.     }
  345.     }
  346.     for (i = nrh + 1; i <= srh; i++) {
  347.     if (!(m[i] = (float GPFAR *) gp_alloc((unsigned long) (nch - ncl + 1) * sizeof(float), NULL))) {
  348.         free_matrix(m, nrl, i - 1, nrl, sch);
  349.         int_error("not enough memory to extend matrix", NO_CARET);
  350.         return NULL;
  351.     }
  352.     m[i] -= ncl;
  353.     }
  354.     return m;
  355. }
  356. /*
  357.    this routine carves a large matrix down to size
  358.  */
  359. float GPFAR *GPFAR * retract_matrix(a, nrl, nrh, ncl, nch, srh, sch)
  360. register float GPFAR *GPFAR * a;
  361. register int nrl, nrh, ncl, nch;
  362. register int srh, sch;
  363. {
  364.     register int i;
  365.     register float GPFAR *GPFAR * m;
  366.  
  367.     for (i = srh + 1; i <= nrh; i++) {
  368.     free_vector(a[i], ncl, nch);
  369.     }
  370.  
  371.     m = (float GPFAR * GPFAR *) gp_realloc((void *) (a + nrl), (unsigned long) (srh - nrl + 1) * sizeof(float GPFAR *), "retract matrix");
  372.  
  373.     m -= nrl;
  374.  
  375.     if (sch != nch) {
  376.     for (i = nrl; i <= srh; i++)
  377.         if (!(m[i] = retract_vector(m[i], ncl, nch, sch))) { {    /* Shrink rows */
  378.             free_matrix(m, nrl, srh, ncl, sch);
  379.             int_error("not enough memory to retract matrix", NO_CARET);
  380.             return NULL;
  381.         }
  382.         }
  383.     }
  384.     return m;
  385. }
  386.  
  387. float
  388. GPFAR *GPFAR * convert_matrix(a, nrl, nrh, ncl, nch)
  389. float GPFAR *a;
  390. register int nrl, nrh, ncl, nch;
  391.  
  392. /* allocate a float matrix m[nrl...nrh][ncl...nch] that points to the
  393.    matrix declared in the standard C manner as a[nrow][ncol], where 
  394.    nrow=nrh-nrl+1, ncol=nch-ncl+1.  The routine should be called with
  395.    the address &a[0][0] as the first argument.  This routine does
  396.    not free the memory used by the original array a but merely assigns
  397.    pointers to the rows. */
  398.  
  399. {
  400.     register int i, j, ncol, nrow;
  401.     register float GPFAR *GPFAR * m;
  402.  
  403.     nrow = nrh - nrl + 1;
  404.     ncol = nch - ncl + 1;
  405.     m = (float GPFAR * GPFAR *) gp_alloc((unsigned long) (nrh - nrl + 1) * sizeof(float GPFAR *), "convert_matrix");
  406.     m -= nrl;
  407.  
  408.     m[nrl] = a - ncl;
  409.     for (i = 1, j = nrl + 1; i <= nrow - 1; i++, j++)
  410.     m[j] = m[j - 1] + ncol;
  411.     return m;
  412. }
  413.  
  414.  
  415. void free_convert_matrix(b, nrl, nrh, ncl, nch)
  416. float GPFAR *GPFAR * b;
  417. register int nrl, nrh, ncl, nch;
  418. {
  419.     free((char *) (b + nrl));
  420. }
  421.